const Service = require('egg').Service;
const fs = require('fs');
const path = require('path');
const FolderScanner = require('@moyufed/folder-scanner');
const unzipper = require('unzipper'); // 用来解压文件
// https://stackoverflow.com/questions/31645738/how-to-create-full-path-with-nodes-fs-mkdirsync
const mkdirp = require('mkdirp'); // 用来创建文件目录
//管道读入一个虫洞。
const sendToWormhole = require('stream-wormhole');

class FileService extends Service {
    async uploadPackage() {
        const ctx = this.ctx;
        const { helper } = this.ctx;
        let siteId;
        let cdn;
        let part;
        let result = true;
        // 多文件上传
        const parts = ctx.multipart();
        // parts() 返回 promise 对象
        while ((part = await parts()) != null) {
            if (part.length) {
                // 这是 busboy 的字段
                // console.log('field: ' + part[0]);
                // console.log('value: ' + part[1]);
                // console.log('valueTruncated: ' + part[2]);
                // console.log('fieldnameTruncated: ' + part[3]);
                if (part[0] && part[1] && part[0] === 'id') {
                    siteId = part[1];
                }
            } else {
                if (!cdn && siteId) {
                    cdn = await ctx.service.cdn.findCdn(siteId)
                }
                if (!part.filename) {
                    // 这时是用户没有选择文件就点击了上传(part 是 file stream，但是 part.filename 为空)
                    // 需要做出处理，例如给出错误提示消息
                    return;
                }
                // part 是上传的文件流
                // console.log('field: ' + part.fieldname);
                // console.log('filename: ' + part.filename);
                // console.log('encoding: ' + part.encoding);
                // console.log('mime: ' + part.mime);
                // 文件处理，上传到云存储等等
                try {
                    const filename = part.filename;
                    const name = filename.split('.zip')[0];
                    let destDir;
                    let v;
                    if (cdn) {
                        // 如果有CDN站点，则根据该站点来进行文件上传，先判断选择的文件是否和站点租户ID一致
                        if (cdn.tenantId !== name) {
                            throw new Error(filename + '不是该站点的包');
                        }
                        if(cdn.uploadType === 2) {
                            const nv = helper.getCurrentTime();
                            destDir = path.resolve(process.cwd(), 'upload', ctx.app.config.envType[cdn.env], ctx.app.config.tenantType[cdn.type], cdn.tenantId, nv);
                            v = await ctx.model.Version.findOneAndUpdate(
                                { tenantId: cdn.tenantId, version: nv },
                                { tenantId: cdn.tenantId, version: nv, siteId: cdn._id, type: cdn.type, status: 0, folderName: name },
                                { new: true, upsert: true }
                            )
                        } else {
                            destDir = path.resolve(process.cwd(), 'upload', ctx.app.config.envType[cdn.env], ctx.app.config.tenantType[cdn.type], cdn.tenantId, this._getNextVersion(cdn.version));
                            v = await ctx.model.Version.findOneAndUpdate(
                                { tenantId: cdn.tenantId, version: this._getNextVersion(cdn.version) },
                                { tenantId: cdn.tenantId, version: this._getNextVersion(cdn.version), siteId: cdn._id, type: cdn.type, status: 0, folderName: name },
                                { new: true, upsert: true }
                            )
                        }
                        if (v) {
                            // 更新cdn站点版本对应的版本ID
                            cdn = await ctx.service.cdn.updateCdn(siteId, { newVersion: v._id })
                        }
                    } else {
                        destDir = path.resolve(process.cwd(), 'upload', 'web', name);
                    }
                    if (!fs.existsSync(destDir)) {
                        // 也可以使用 fs-extra 库
                        await mkdirp(destDir);
                    }
                    const unzipResult = await this._unzipPackage(part, destDir);
                    if(cdn) {
                        return cdn
                    }
                    result = result && unzipResult;
                } catch (err) {
                    // 必须将上传的文件流消费掉，要不然浏览器响应会卡死
                    await sendToWormhole(part);
                    throw err;
                }
            }
        }
        return result

        // 单文件上传
        // const stream = await ctx.getFileStream();
        // const filename = stream.filename;
        // const name = filename.split('.zip')[0];
        // const destDir = path.resolve(process.cwd(), 'upload', 'package', name);
        // // console.log(process.execPath)
        // // console.log(__dirname)
        // // console.log(process.cwd())
        // if (!fs.existsSync(destDir)) {
        //     // 也可以使用 fs-extra 库
        //     await mkdirp(destDir);
        // }
        // const unzipResult = await this._unzipPackage(stream, destDir);
        // if (unzipResult === true) {
        //     console.log("解压成功");
        //     const folderScanner = new FolderScanner({
        //         location: path.resolve(process.cwd(), 'upload'),
        //         rootFolder: 'package'
        //     });
        //     console.log(folderScanner.getFiles());
        //     ctx.body = {
        //         code: 200,
        //         data: {},
        //         success: true,
        //         msg: `上传成功`
        //     }
        // }
    }

    _getNextVersion(version) {
        const v = version.split('.')
        v[2] = parseInt(v[2]) + 1
        return v.join('.')
    }

    _unzipPackage(stream, path) {
        return new Promise((resolve, reject) => {
            stream.pipe(unzipper.Extract({ path }))
                .on('entry', entry => {
                })
                .on("close", data => {
                    console.log("解压成功");
                    resolve(true);
                })
                .on('error', e => {
                    reject(e);
                });
        })
    }
}

module.exports = FileService;